package org.xxpay.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.xxpay.core.common.constant.Constant;
import org.xxpay.core.common.constant.RetEnum;
import org.xxpay.core.common.exception.ServiceException;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.AlipayCash;
import org.xxpay.core.entity.AlipayCashDetail;
import org.xxpay.core.entity.AlipayCashUser;
import org.xxpay.core.entity.PayInterfaceTypeTemplate;
import org.xxpay.core.service.IXxPayAlipayCashService;
import org.xxpay.pay.channel.alipay.AlipayCampaignCashService;
import org.xxpay.pay.mq.BaseNotify4AlipayCash;
import org.xxpay.pay.service.CommonService;

import java.util.ArrayList;
import java.util.List;

/**
 *
 */
@Service(interfaceName = "org.xxpay.core.service.IXxPayAlipayCashService", version = Constant.XXPAY_SERVICE_VERSION, retries = Constant.DUBBO_RETRIES)
public class XxPayAlipayCashServiceImpl implements IXxPayAlipayCashService {

    private static final MyLog logger = MyLog.getLog(XxPayAlipayCashServiceImpl.class);

    @Autowired
    private CommonService commonService;

    @Autowired
    private AlipayCampaignCashService alipayCampaignCashService;

    @Autowired
    private BaseNotify4AlipayCash baseNotify4AlipayCash;


    @Override
    public Integer createAlipayCash(AlipayCash cash) {

        //验证基础信息
        if(cash == null) throw new ServiceException(RetEnum.RET_COMM_PARAM_NOT_FOUND);

        //判断必要参数
        if(StringUtils.isAnyBlank(cash.getCouponName(), cash.getPrizeMsg())){
            throw new ServiceException(RetEnum.RET_COMM_PARAM_NOT_FOUND);
        }

        //判断时间范围 TODO

        //查询账号模板
        PayInterfaceTypeTemplate accountTemplate = commonService.payInterfaceTypeTemplateService.findById(cash.getAccountTemplateId());

        if(accountTemplate == null) throw new ServiceException(RetEnum.RET_COMM_PARAM_NOT_FOUND);


        if(!"alipay".equals(accountTemplate.getIfTypeCode())){ //支付类型必须是：alipay
            throw new ServiceException(RetEnum.RET_COMM_PARAM_ERROR);
        }
        cash.setPrizeType("fixed"); //默认-固定金额
        cash.setSendFreqency("L100"); //每用户领取次数：终身100次

        //获取封装用户
        JSONArray mgrUserIdsJSON = JSON.parseArray(cash.getPsStringVal("mgrUserIds")); //解析json格式
        if(mgrUserIdsJSON.size() <= 0) throw new ServiceException(RetEnum.RET_SERVICE_NOT_FOUND_AVAILABLE_ALIPAY_USER);  //判断参数是合法

        //转换为Integer格式
        List<Integer> mgrUserIds = new ArrayList<>(); mgrUserIdsJSON.stream().forEach(id -> mgrUserIds.add(Integer.parseInt(id.toString())));

        //查询用户
        List<AlipayCashUser> userList = commonService.alipayCashUserService.selectByAvailableWithMgrUserIds(mgrUserIds);
        if(userList.isEmpty()) throw new ServiceException(RetEnum.RET_SERVICE_NOT_FOUND_AVAILABLE_ALIPAY_USER); //不存在可用分账用户

        int userSizeDistinct = userList.size(); //实际用户数量
        final long singleMaxMoney = Long.parseLong(cash.getPsStringVal("singleMaxMoney")); //单个红包最大金额【参数】
        if(cash.getTotalMoney() / (100 * userSizeDistinct) > singleMaxMoney ){ //假设每个用户最高领取次数为100 ， 并且平均金额大于了200,则调起支付宝可能出现失败，提示用户创建失败。
            throw new ServiceException(RetEnum.RET_MGR_ALIPAY_CASH_GT_SINGLE_AMOUNT);
        }

        List<AlipayCashUser> finalUser = new ArrayList<>(); //最终领包用户集合

        long avgMoney = cash.getTotalMoney() / userSizeDistinct; //平均金额

        if(avgMoney > singleMaxMoney){ //如果人均大于 200元，需要增加领取次数

            long subAmount = cash.getTotalMoney(); //剩余金额
            long forCount = (cash.getTotalMoney() / singleMaxMoney ) + 1; //取整 + 1

            for(int i = 0; i < forCount; i++){
                for(AlipayCashUser user: userList){

                    AlipayCashUser clonedUser = (AlipayCashUser)user.clone(); //克隆对象信息
                    if(subAmount <= 0) break; //当剩余金额 不足以分配时
                    //最大分配200元， 如不足200按照实际分配
                    clonedUser.setPsVal("planAmount", subAmount > singleMaxMoney ? singleMaxMoney : subAmount);
                    finalUser.add(clonedUser);
                    subAmount = subAmount - clonedUser.getPsLongVal("planAmount"); //金额减少
                }
            }
        }else{ //平均分配

            long avgAmount = cash.getTotalMoney() / userList.size() ; //平均金额， 向下取整
            for(int i = 0 ; i < userList.size(); i++){

                if( i != (userList.size()-1) ){ //非最后一个
                    userList.get(i).setPsVal("planAmount", avgAmount);
                    continue;
                }

                //最后一个金额 = 总金额 - （平均金额 * （数量 -1 ））， 避免出现 1元/3份 不能平均分的问题。
                long subAmount = cash.getTotalMoney() - (avgAmount * (userList.size() - 1));
                userList.get(i).setPsVal("planAmount", subAmount);
            }
        }

        cash.setTotalNum(finalUser.size()); //红包个数

       //分账明细  入库对象
        List<AlipayCashDetail> addDetails = new ArrayList<>();

        //调起支付宝接口
        boolean isTrue = alipayCampaignCashService.create(accountTemplate.getParamTemplate(), cash);
        if(isTrue){
            cash.setTaskStatus(AlipayCash.TASK_STATUS_CREATE_SUCCESS); //任务创建成功

            for(AlipayCashUser user : finalUser){  //仅红包创建成功，才记录明细
                AlipayCashDetail detail = new AlipayCashDetail();
                detail.setCashUserId(user.getId());
                detail.setAlipayLoginId(user.getAlipayLoginId());
                detail.setPlanAmount(user.getPsLongVal("planAmount")); //预计分账金额, 自动向下取整。
                detail.setStatus(AlipayCashDetail.STATUS_WAIT); //待发放
                detail.setBelongUserId(user.getCreateUserId());
                addDetails.add(detail);
            }
        }else{
            cash.setTaskStatus(AlipayCash.TASK_STATUS_CREATE_FAIL); //任务创建失败
        }

        //入库操作 返回操作ID
        return commonService.alipayCashService.save(cash, addDetails);
    }

    @Override
    public String updateInfoFromAlipay(Integer cashId) {

        AlipayCash dbRecord = commonService.alipayCashService.findById(cashId);
        if(dbRecord == null) return null;

        //处理中状态，不可变更状态
        if (StringUtils.isBlank(dbRecord.getAlipayCrowdNo()) || dbRecord.getTaskStatus() == AlipayCash.TASK_STATUS_ING
        ) {
            return null;
        }

        //查询账号模板
        PayInterfaceTypeTemplate accountTemplate = commonService.payInterfaceTypeTemplateService.findById(dbRecord.getAccountTemplateId());

        if(accountTemplate == null) throw new ServiceException(RetEnum.RET_COMM_PARAM_NOT_FOUND);

        //查询支付宝上游信息
        AlipayCash alipayRecord = alipayCampaignCashService.query(accountTemplate.getParamTemplate(), dbRecord.getAlipayCrowdNo());
        if(alipayRecord == null) return null; //查询失败

        //更新入库
        AlipayCash updateRecord = new AlipayCash();
        updateRecord.setId(cashId);
        updateRecord.setAlipayStatus(alipayRecord.getAlipayStatus());
        updateRecord.setAlipaySendAmount(alipayRecord.getAlipaySendAmount());
        commonService.alipayCashService.update(updateRecord);

        //返回支付宝最新状态
        return alipayRecord.getAlipayStatus();

    }

    @Override
    public void triggerAlipayCash(Integer cashId) {

        AlipayCash dbRecord = commonService.alipayCashService.findById(cashId);
        if(dbRecord == null) throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);

        //处理中状态，不可变更状态
        if (StringUtils.isBlank(dbRecord.getAlipayCrowdNo()) || dbRecord.getTaskStatus() != AlipayCash.TASK_STATUS_CREATE_SUCCESS
        ) {
            if(dbRecord == null) throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);
        }

        //更新入库
        AlipayCash updateRecord = new AlipayCash();
        updateRecord.setId(cashId); updateRecord.setTaskStatus(AlipayCash.TASK_STATUS_ING); //处理中...
        commonService.alipayCashService.update(updateRecord);

        //调起MQ发红包
        baseNotify4AlipayCash.doNotify(cashId);

    }

    @Override
    public String modifyStatus(Integer cashId, String modifyStatus) {

        AlipayCash dbRecord = commonService.alipayCashService.findById(cashId);
        if(dbRecord == null) throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);


        if (StringUtils.isBlank(dbRecord.getAlipayCrowdNo())) {
            throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);
        }

        //处理中 | 创建失败 , 不可更改状态
        if(dbRecord.getTaskStatus() == AlipayCash.TASK_STATUS_ING || dbRecord.getTaskStatus() == AlipayCash.TASK_STATUS_CREATE_FAIL){
            throw new ServiceException(RetEnum.RET_COMM_OPERATION_FAIL);
        }

        //查询账号模板
        PayInterfaceTypeTemplate accountTemplate = commonService.payInterfaceTypeTemplateService.findById(dbRecord.getAccountTemplateId());
        if(accountTemplate == null) throw new ServiceException(RetEnum.RET_COMM_PARAM_NOT_FOUND);


        JSONObject result = alipayCampaignCashService.modifyStatus(accountTemplate.getParamTemplate(), dbRecord.getAlipayCrowdNo(), modifyStatus);
        if(result.getBoolean("isSuccess")){ //更新成功

            this.updateInfoFromAlipay(cashId); //更新最新状态
            return null;
        }else{
            return result.getString("errMsg");
        }
    }
}
